package com.heiyanquan.security.browser.config;

import com.heiyanquan.security.authentication.AuthenticationFailureAction;
import com.heiyanquan.security.authentication.AuthenticationSuccessAction;
import com.heiyanquan.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig;
import com.heiyanquan.security.core.properties.SecurityConstants;
import com.heiyanquan.security.core.properties.SecurityProperties;
import com.heiyanquan.security.core.validate.ValidatorCodeFilter;
import com.heiyanquan.security.core.validate.sms.SmsCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author dingaolin
 * @Date: 2017/12/9 0009.
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private AuthenticationSuccessAction authenticationSuccessAction;

    @Autowired
    private AuthenticationFailureAction authenticationFailureAction;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    @Bean
    public PasswordEncoder passwordEncoder() {
        // TODO: 2017/12/9 0009 自定义实现 PasswordEncoder 即可
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ValidatorCodeFilter validatorCodeFilter = new ValidatorCodeFilter();
        validatorCodeFilter.setAuthenticationFailureHandler(authenticationFailureAction);
        validatorCodeFilter.setSecurityProperties(securityProperties);
        validatorCodeFilter.afterPropertiesSet();

        SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
        smsCodeFilter.setAuthenticationFailureHandler(authenticationFailureAction);
        smsCodeFilter.setSecurityProperties(securityProperties);
        smsCodeFilter.afterPropertiesSet();

        // 表单登录
        http.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(validatorCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                    .loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
                    .loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)
                    .successHandler(authenticationSuccessAction)
                    .failureHandler(authenticationFailureAction)
                    .and()
                .rememberMe()
                    .tokenRepository(persistentTokenRepository())
                    .tokenValiditySeconds(securityProperties.getBrowserProperties().getRememberMeSeconds())
                    .userDetailsService(userDetailsService)
                    // basic 弹窗登录
                    //http.httpBasic()
                    .and()
                .authorizeRequests()
                    .antMatchers(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                            securityProperties.getBrowserProperties().getLoginPage(),
                            "/code/*").permitAll()
                    .anyRequest()
                    .authenticated()
                    .and()
                .csrf().disable()
                .apply(smsCodeAuthenticationSecurityConfig);
    }
}
